package com.htthorizon.gateway.filter;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.json.JSONObject;
import com.htthorizon.common.core.constant.HttpStatus;
import com.htthorizon.common.core.constant.SecurityConstants;
import com.htthorizon.common.core.context.SecurityContextHolder;
import com.htthorizon.common.core.utils.JwtUtils;
import com.htthorizon.common.core.utils.ServletUtils;
import com.htthorizon.common.core.utils.StringUtils;
import com.htthorizon.common.core.utils.ip.IpUtils;
import com.htthorizon.common.redis.service.RedisService;
import com.htthorizon.gateway.config.properties.IgnoreWhiteProperties;
import com.htthorizon.system.api.RemoteLogService;
import com.htthorizon.system.api.domain.SysLogininfor;
import com.htthorizon.system.api.domain.SysOperLog;
import com.htthorizon.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author Brilliant
 */
@Component
public class UniqueFilter implements GlobalFilter, Ordered {

    @Autowired
    private RedisService redisService;

    @Value("${unique}")
    private boolean unique;

    @Autowired
    private IgnoreWhiteProperties ignoreWhite;
//
//    @Autowired
//    private RemoteLogService remoteLogService;

//    public static void main(String[] args) {
//        String content = "test中文";
//
////随机生成密钥
////        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
////
//////构建
////        System.out.println(new java.lang.String(key, CharsetUtil.CHARSET_UTF_8));
//
//
////加密
////        byte[] encrypt = aes.encrypt(content);
//////解密
////        byte[] decrypt = aes.decrypt(encrypt);
//
////加密为16进制表示
//        String encryptHex = aes.encryptHex(content);
////解密为字符串
//
//        System.out.println(decryptStr);
//    }
//public static void main(String[] args) {
//    String method="GET";
//            if(!method.equals("GET")&&!method.contains("upload")){
//                System.out.println(111);
//            }
//    System.out.println(222);
//}
public static void main(String[] args) {
    String str="/manage/model/search/list?searchJson=%7B%22pageNum%22%3A1%2C%22pageSize%22%3A10%2C%22std_city_org_nm%22%3A%22%22%7D&sourceId=104&modelId=101";
    String s="$2a$04$BYqwM.8NXsse7cNRgU2ZKOtqXgmFWIThx3J9eXJ2ZtbBJcV5NU8cK";
    String s1="XOPb534Lj1sjwujueACr3imQfasasseJjO0UXBoNidpxvDCmh9m1jEzlHUhIlucNO7SHbBn9H4Lvo+/LaOa7dGQmf16XT3nIRJaTInbcdEYfd7c28JX/RRpD536+No8Dxfjxfrxspgl9k/RzfFWQ9IREfUQcVDs/V/zK7toZ5/AXTmIdayhMopahQ53ZpbwZ";
    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(10);
    System.out.println(passwordEncoder.matches(str, s));

    SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, "KWCNJQWNUAOW8E19".getBytes());
//    String s2 = aes.decryptStr(s1);
    byte[] decrypt = aes.decrypt(str);
    System.out.println(new String(decrypt));

//    System.out.println(s2);
//    System.out.println(s2.equals(str));
//    String s1= "/manage/model/search/list?searchJson=%7B%22pageNum%22:1,%22pageSize%22:10,%22std_city_org_nm%22:%22%22%7D&sourceId=104&modelId=101";
//    String replace = s1.replace(":", "%3A");
//    String replace1 = replace.replace(",", "%2C");
//    System.out.println(replace1.equals(str));
}
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpRequest.Builder mutate = request.mutate();
        URI uri = request.getURI();

        String path = uri.getPath();
        String query = uri.getQuery();
        HttpMethod method = request.getMethod();
        if (method.matches("GET")||path.contains("upload") ) {
            String str = null;

            if (!Objects.isNull(query)) {
                String encode = URLUtil.encode(query);
                str = path + "?" + encode;
            } else {
                str = path;
            }


//       this.verify(request);


            String first = request.getHeaders().getFirst("x-Forwarded-For");
            String first1 = request.getHeaders().getFirst("X-Real-IP");
            HttpHeaders headers1 = request.getHeaders();
            List<String> list1 = headers1.get("authorization");
            String userName = null;
            if (list1 != null && !(list1.isEmpty())) {
                String token = list1.get(0);
                userName = JwtUtils.getUserName(token);
            }

            // 跳过不需要验证的路径
            if (StringUtils.matches(path, ignoreWhite.getWhites())) {
                return chain.filter(exchange);
            }
            if (
                  request.getURI().getPath().contains("password")
//                   || request.getURI().getPath().contains("search/list")
                 || request.getURI().getPath().contains("statics")
                   ||  request.getURI().getPath().contains("redis")) {
                return chain.filter(exchange);
            }

            if (unique) {
                boolean flag=true;
                HttpHeaders headers = request.getHeaders();
                List<String> list = headers.get("time");
                String s = list.get(0);
                BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(10);
                SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, "KWCNJQWNUAOW8E19".getBytes());
                if (request.getURI().getPath().contains("search/list")){
                    String replace = str.replace(":", "%3A");
                    str = replace.replace(",", "%2C");
                    System.out.println("////");
                    System.out.println(str);
                    System.out.println(s);
                    String s1 = aes.decryptStr(s);
                    flag= s1.equals(str);
                    System.out.println("是否相等"+flag);
                }else {
                    flag= passwordEncoder.matches(str,s);
                }


                if (!flag) {

//                SysOperLog operLog = new SysOperLog();
//                operLog.setLevel(3);
//                operLog.setType("系统级");
//                operLog.setStatus(1);
//                operLog.setErrorMsg("会话篡改");
//
//                // 设置请求方式
//                operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
//
//                // 保存数据库
//
//                try {
//                    remoteLogService.saveLog(operLog, SecurityConstants.INNER);
//                } catch (Exception e) {
//
//                }
                    SysOperLog sysLogininfor = SysOperLog.build(userName, IpUtils.getIpAddr1(exchange.getRequest()), "会话篡改", request.getMethod().toString(),path,request);
                    redisService.setCacheObject("log:" + sysLogininfor.getCreateTime(), sysLogininfor);
                    return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "伪造的key", 400);
                }
                try {
                    String cacheObject = redisService.getCacheObject(path + list.get(0));
                    if (cacheObject != null) {
                        SysOperLog sysLogininfor = SysOperLog.build(userName, IpUtils.getIpAddr1(exchange.getRequest()), "会话重放", request.getMethod().toString(),path,request);
                        redisService.setCacheObject("log:" + sysLogininfor.getCreateTime(), sysLogininfor);
                        return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "重放或会话篡改", 400);
                    }
                    redisService.setCacheObject(path + list.get(0), "time", 1L, TimeUnit.SECONDS);
                    return chain.filter(exchange.mutate().request(mutate.build()).build());

                } catch (NullPointerException e) {
                    return chain.filter(exchange.mutate().request(mutate.build()).build());
                } catch (Exception e) {
                    e.printStackTrace();
                    SysOperLog sysLogininfor = SysOperLog.build(userName, IpUtils.getIpAddr1(exchange.getRequest()), "未添加指定key", request.getMethod().toString(),path);
                    redisService.setCacheObject("log:" + sysLogininfor.getCreateTime(), sysLogininfor);
                    return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "未添加指定key", 400);
                }
            }
        }
        return chain.filter(exchange.mutate().request(mutate.build()).build());
    }

//    private void verify(ServerHttpRequest request) {
//        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, "KWCNJQWNUAOW8E19".getBytes());
//        Flux<DataBuffer> body = request.getBody();
//      body.flatMap(readBody)
//              .doOnNext(body -> {
//                  // 处理请求体内容
//                  System.out.println("请求体内容: " + body);
//              })
//              .then(chain.filter(exchange));
//
//        System.out.println(body);
//        System.out.println();
//
//    }

    @Override
    public int getOrder() {
        return -200000;
    }
}
